//
//  GridView.m
//  McRemote
//
//  Created by Yuncheng Shen on 12/11/11.
//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//

#import "GridView.h"

@interface GridView () 

@property (nonatomic, strong) NSMutableArray *cells;

- (CGPoint)positionOfCellAtIndex:(NSInteger)index;
- (void)reset;
- (void)loadData;

@end

@implementation GridView

#pragma mark - accessors

@synthesize gridViewDelegate = _gridViewDelegate;
@synthesize gridViewDataSource = _gridViewDataSource;
@synthesize pageCount = _pageCount;
@synthesize editing = _editing;
@synthesize cells;

- (CGSize)cellSize
{
    return CGSizeMake(self.frame.size.width/3, self.frame.size.height/3);
}

- (void)setPageCount:(NSInteger)pageCount
{
    if (pageCount > _pageCount) 
    {
        for (int i = 0; i<9*(pageCount-_pageCount); i++) 
        {
            [self.cells addObject:[NSNull null]];
        }
    }
    else if (pageCount < _pageCount) 
    {
        for (int i = 0; i<9*(_pageCount-pageCount); i++) 
        {
            int idx = self.cells.count-1;
            
            id cell = [self.cells objectAtIndex:idx];
            if (cell != [NSNull null]) 
            {
                GridViewCell *c = (GridViewCell *)cell;
                [c removeFromSuperview];
            }
            
            [self.cells removeObjectAtIndex:idx];
        }
    }
    else return;
        
    _pageCount = pageCount;
    
    self.contentSize = CGSizeMake(self.frame.size.width, self.frame.size.height*pageCount);
    self.alwaysBounceVertical = YES;
}

- (void)setEditing:(BOOL)editing
{
    if (_editing == editing) return;
    
    _editing = editing;
    
    if (!(self.gridViewDataSource && [self.gridViewDataSource respondsToSelector:@selector(gridView:canEditCellAtIndex:)])
        || !(self.gridViewDelegate && [self.gridViewDelegate respondsToSelector:@selector(gridView:editingStyleForCellAtIndex:)])) {
        NSLog(@"Please implement the following protocols:\nFor gridViewDataSource: 1) gridView:canEditCellAtIndex: 2) gridView:commitEditingStyle:forCellAtIndex:\nFor gridViewDelegate: 1) gridView:editingStyleForCellAtIndex:\nif you want to set editting to YES");
        return;
    }
    
    if (editing) {
        for (int i = 0; i<[self.cells count]; i++) 
        {
            //according to dataSource, if the cell can be edited,
            //  set the cell to editingStyle given the style specified by delegate
            if ([self.gridViewDataSource gridView:self canEditCellAtIndex:i]) 
            {
                GridViewCellEditingStyle editingStyle = [self.gridViewDelegate gridView:self editingStyleForCellAtIndex:i];
                            
                if (editingStyle == GridViewCellEditingStyleInsert) {
                    [self insertCell:[GridViewCell emptyGridCell] AtIndex:i];
                }
                
                GridViewCell *cell = [self cellAtIndex:i];
                cell.editingStyle = editingStyle;
            }
        }
    }
    else {
        for (int i = 0; i<[self.cells count]; i++) 
        {
            GridViewCell *cell = [self cellAtIndex:i];
            if (cell.editingStyle == GridViewCellEditingStyleInsert) {
                [self deleteCellAtIndex:i];
            }
            else {
                cell.editingStyle = GridViewCellEditingStyleNone;
            }
        }
    }
}

#pragma mark - view life cycle

- (void)awakeFromNib
{
    self.cells = [[NSMutableArray alloc] initWithCapacity:9];
    
    self.gridViewDelegate = nil;
    self.gridViewDataSource = nil;
    _pageCount = 0;
    _editing = NO;
    
    self.scrollEnabled = YES;
    self.pagingEnabled = YES;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        
        self.cells = [[NSMutableArray alloc] initWithCapacity:9];
        
        self.gridViewDelegate = nil;
        self.gridViewDataSource = nil;
        _pageCount = 0;
        _editing = NO;
        
        self.scrollEnabled = YES;
        self.pagingEnabled = YES;
    }
    
    return self;
}

#pragma mark - API

- (NSInteger)indexForCell:(GridViewCell *)cell
{
    return [self.cells indexOfObject:cell];
}

- (GridViewCell *)cellAtIndex:(NSInteger)index
{
    if (index >= [self.cells count]) {
        return nil;
    }
    
    id cell = [self.cells objectAtIndex:index];
    if (cell == [NSNull null]) {
        return nil;
    }
    else return cell;
}

- (BOOL)insertCell:(GridViewCell *)cell AtIndex:(NSInteger)index
{
    if (index > [self.cells count]) {
        return NO;
    }
    
    cell.gridView = self;
    cell.editingStyle = GridViewCellEditingStyleNone;
    
    id oldCell = [self.cells objectAtIndex:index];
    if (oldCell != [NSNull null]) {
        GridViewCell *oc = (GridViewCell *)oldCell;
        [oc removeFromSuperview];
    }
    
    //add to cells array
    [self.cells replaceObjectAtIndex:index withObject:cell];
    
    //add cell to grid view
    CGPoint origin = [self positionOfCellAtIndex:index];
    cell.frame = CGRectMake(origin.x, origin.y, self.cellSize.width, self.cellSize.height);
    
    [self addSubview:cell];
    
    return YES;
}

- (BOOL)deleteCellAtIndex:(NSInteger)index
{
    if (index >= [self.cells count]) {
        return NO;
    }
    
    id cell = [self.cells objectAtIndex:index];
    if (cell != [NSNull null]) 
    {
        [cell removeFromSuperview];
        [self.cells replaceObjectAtIndex:index withObject:[NSNull null]];
        
        return YES;
    }
    else return NO;
}

- (void)reloadData
{
    if (!self.gridViewDataSource) {
        return;
    }
    
    [self reset];
    [self loadData];
}

#pragma mark - util

- (void)reset
{
    self.pageCount = 0;
}

- (void)loadData
{
    self.pageCount = [self.gridViewDataSource numberOfPagesInGridView:self];
    
    for (int i = 0; i<self.pageCount*9; i++) 
    {
        GridViewCell *cell = [self.gridViewDataSource gridView:self cellAtIndex:i];
        if (cell) {
            [self insertCell:cell AtIndex:i];
        }
    }
}

- (CGPoint)positionOfCellAtIndex:(NSInteger)index
{
    int pageNumber = index/9;
    
    int columnNumber = index%3;
    float x = self.cellSize.width*columnNumber;
    
    int realRowNumber = index/3;
    int rowNumber = realRowNumber%3;
    float y = self.cellSize.height*rowNumber + pageNumber*self.frame.size.height;
    
    return CGPointMake(x, y);
}

#pragma mark - implemente informal protocol
- (void)deleteCell:(GridViewCell *)cell
{
    NSInteger index = [self indexForCell:cell];
    [self.gridViewDataSource gridView:self commitEditingStyle:GridViewCellEditingStyleDelete forCellAtIndex:index];
}

- (void)tapOnCell:(GridViewCell *)cell
{
    if (self.gridViewDelegate 
        && [self.gridViewDelegate respondsToSelector:@selector(gridView:tapOnCell:)]) {
        [self.gridViewDelegate gridView:self tapOnCell:cell];
    }
    
    if (GridViewCellEditingStyleInsert == cell.editingStyle) {
        NSInteger index = [self indexForCell:cell];
        [self.gridViewDataSource gridView:self commitEditingStyle:GridViewCellEditingStyleInsert forCellAtIndex:index];
    }
}

- (void)longPressOnCell:(GridViewCell *)cell
{
    if (self.gridViewDelegate
        && [self.gridViewDelegate respondsToSelector:@selector(gridView:longPressOnCell:)]) {
        [self.gridViewDelegate gridView:self longPressOnCell:cell];
    }
}


@end
